import sys
from PyQt5.QtWidgets import QMainWindow,QApplication,QWidget
from Ui_untitled import Ui_MainWindow  #导入你写的界面类
import os
from PyQt5.QtWidgets import QFileDialog,QMessageBox
from intelhex import IntelHex

class MyMainWindow(QMainWindow,Ui_MainWindow): #这里也要记得改
    def __init__(self,parent =None):
        super(MyMainWindow,self).__init__(parent)
        self.setupUi(self)


    # 选择单个文件
    def Select_a_single_file(self, dispaly_label):
        # file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Binary Files (*.bin);All Files (*)")
        file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Binary Files (*.bin);;All Files (*)")
        if file_path:
            print(file_path)
            # self.lineEdit_BootPath.setText(file_path)
            dispaly_label.setText(file_path)


    def ui_param_init(self):
        self.lineEdit_BootPath.setText("")
        self.lineEdit_AppPath.setText("")
        
        self.lineEdit_BootAddr.setText("0x08000000")
        self.lineEdit_BootSize.setText("0x10000")

        self.lineEdit_AppAddr.setText("0x08010000")
        self.lineEdit_AppSize.setText("0x10000")
        

        self.lineEdit_FirmwareName.setText("all.hex")
        self.lineEdit_FirmwareVersion.setText("1.0.0")
        self.lineEdit_FirmwarePath.setText("output/")

        
    # 检查输入框内容是否合法
    def check_lable_input(self):
        
        if not os.path.isfile(self.lineEdit_BootPath.text()):
            QMessageBox.critical(self, "警告", "BOOT bin路径未填写", QMessageBox.Ok)
            return False
        if not os.path.isfile(self.lineEdit_AppPath.text()):
            QMessageBox.critical(self, "警告", "APP bin路径未填写", QMessageBox.Ok)
            return False
        if not self.lineEdit_BootAddr.text():
            QMessageBox.critical(self, "警告", "BOOT地址输入有误", QMessageBox.Ok)
            return False
        if not self.lineEdit_BootSize.text():
            QMessageBox.critical(self, "警告", "BOOT大小输入有误", QMessageBox.Ok)
            return False
        if not self.lineEdit_AppAddr.text():
            QMessageBox.critical(self, "警告", "APP地址输入有误", QMessageBox.Ok)
            return False
        if not self.lineEdit_AppSize.text():
            QMessageBox.critical(self, "警告", "APP大小输入有误", QMessageBox.Ok)
            return False
        if not self.lineEdit_FirmwareName.text():
            QMessageBox.critical(self, "警告", "固件名称未填写", QMessageBox.Ok)
            return False
        if not self.lineEdit_FirmwareVersion.text():
            QMessageBox.critical(self, "警告", "固件版本未填写", QMessageBox.Ok)
            return False
        if not self.lineEdit_FirmwarePath.text():
            QMessageBox.critical(self, "警告", "固件输出路径未填写", QMessageBox.Ok)
            return False
        
        
        return True

    def make_param_sector(self):
        param_sector = bytearray(2048)
        # param_sector[0:16] = b'STM32F407ZGT6'
        param_sector[0] = 0xAA
        param_sector[1] = 0xBB
        param_sector[2] = 0xCC
        param_sector[3] = 0xDD
        
        # 打开一个文件以二进制写入，如果文件不存在将创建文件
        with open('param_sector.bin', 'wb') as bin_file:
            bin_file.write(param_sector)
    
    def merge_all_bin(self):
        boot_bin_path = self.lineEdit_BootPath.text()
        app_bin_path = self.lineEdit_AppPath.text()

        boot_addr_offset = int(self.lineEdit_BootAddr.text(), 16)
        # boot_offset = int(self.lineEdit_BootSize.text(), 16)
        app_addr_offset = int(self.lineEdit_AppAddr.text(), 16)
        # app_offset = int(self.lineEdit_AppSize.text(), 16)

        firmware_name = self.lineEdit_FirmwareName.text()
        firmware_version = self.lineEdit_FirmwareVersion.text()
        firmware_path = self.lineEdit_FirmwarePath.text()

        # output_path = self.lineEdit_FirmwarePath.text()

        if not os.path.exists(firmware_path):
            os.makedirs(firmware_path)

        cfg_bin_path = 'param_sector.bin'


        # 合并两个 bin 文件
        ih = IntelHex()

        # 加载boot bin 文件
        ih.loadbin(boot_bin_path, boot_addr_offset)

        # 加载cfg bin 文件
        ih.loadbin(cfg_bin_path, 0x8006000) 

        # 加载appbin 文件
        ih.loadbin(app_bin_path, app_addr_offset)

        # ih.tofile("./output/make.hex", format='hex')
        ih.tofile(firmware_path+"/"+firmware_name, format='hex')


    def make_firmware(self):
        ret = self.check_lable_input()
        if ret == False:
            return False
        self.make_param_sector()             ## 生成参数扇区文件
        
        self.merge_all_bin()

        QMessageBox.critical(self, "提示", "打包完成", QMessageBox.Ok)


if __name__ == "__main__":
    VERSION = "1.0.0"
    app = QApplication(sys.argv)
    myWin = MyMainWindow()
    
    myWin.show()

    myWin.ui_param_init()
    myWin.setWindowTitle("[MSWL] STM32 固件打包工具"+VERSION)

    
    
    myWin.pushButton_BootBrowse.clicked.connect(lambda: myWin.Select_a_single_file(myWin.lineEdit_BootPath))
    myWin.pushButton_AppBrowse.clicked.connect(lambda: myWin.Select_a_single_file(myWin.lineEdit_AppPath))
    # myWin.pushButton_AppBrowse.clicked.connect(myWin.Select_a_single_file)

    myWin.pushButton_Cancel.clicked.connect(app.quit)
    myWin.pushButton_MakePack.clicked.connect(lambda: myWin.make_firmware())
    sys.exit(app.exec_())    